'''
Created on 01/06/2010

@author: eh01
'''
from xml.etree import ElementTree
from runtime.service import Service
from datastore.resource import Resource
from datastore.uri import Uri
import re
import StringIO
import logging

prefixed_qualified_name_pattern = re.compile(r'(\w*):(\w*)')

class WSDLService(Service):

    def cb_start(self, uri, action, res):
        self.spaces.set_process(Uri('external:edais/artefacts/'), self.cb_get_wsdl_schema)
        
    def cb_stop(self, uri, action, res):
        pass

    def cb_get_wsdl_schema(self, uri, action, res):
        self.logger.log(logging.INFO, "Initial File path %s" % uri)        
        edais_artefacts_path = self.get_edais_artefacts_path(uri)
        self.logger.log(logging.INFO, "Processed File path %s" % edais_artefacts_path)
        if edais_artefacts_path.endswith('.wsdl'):
            rs = self.datastore.find([(Uri('term:base/datastore/resource/type'), Uri('term:eplanning/edais/wsdl')),
                                 (Uri('term:eplanning/edais/artefact/path'), edais_artefacts_path)])[0]
        elif edais_artefacts_path.endswith('.xsd'):
            rs = self.datastore.find([(Uri('term:base/datastore/resource/type'), Uri('term:eplanning/edais/schema')),
                                 (Uri('term:eplanning/edais/artefact/path'), edais_artefacts_path)])[0]
        else:
            raise Exception()
        response_rs = Resource(type='term:base/services/http/response')
        response_rs.content = rs.file_content
        response_rs.content_type = 'text/xml'
        response_rs.content_length = len(response_rs.content)
        return response_rs
    
    def cb_get_schema(self):
        pass
    
    def get_edais_artefacts_path(self, uri):
        """
        Generates the edais artefact path from the spaces uri passed in. This is 
        done by stripping off the prefix of the Uri (i.e. external:edais/artefacts/)
        and then consolidating the suffix of the Uri.s
        
        :param uri: Uri requested from Spaces.
        :rtype: edais artefacts path as a string
        """           
        edais_artefacts_uri_path = Uri(str(uri).replace('external:edais/artefacts/', ''))
        
        # Consolidate the Uri. If the uri happens to have parts in them that are either '../' or './' 
        # perform the appropriate action on the existing path.
        new_uri_parts = []
        for uri_part in edais_artefacts_uri_path.split():
            # means up one level, so pop the last part of the path off
            if uri_part == '../':
                new_uri_parts.pop()
                continue
            # doesn't mean anything really. Just continue with the next part of the path
            elif uri_part == './':
                continue
            else:
                new_uri_parts.append(uri_part)
                
        return ''.join(new_uri_parts)    
            
    def pre_parse_xml_to_add_namespace_data_to_elements(self, xml_fo):
        """
        Parses xml and adds a dictionary to each element in the xml that contains
        all the namespace prefixes (key) and the namespaces (value) that are in scope
        of the xml element.
        
        :param xml_fo: File object containing the xml
        :rtype: Root element of the xml. Element Interface (http://docs.python.org/library/xml.etree.elementtree.html#the-element-interface)
        """           
    ####################################################################################################################
    # NOTES
    ####################################################################################################################
    #         The 'start' and 'end' events represent opening and closing element. They are accompanied by the respective 
    #         Element instance.  By default, only 'end' events are generated
    #         The 'start-ns' and 'end-ns' events notify about namespace declarations. They do not come with Elements.
    #         Instead, the value of the 'start-ns' event is a tuple (prefix, namespaceURI) that designates the 
    #         beginning of a prefix-namespace mapping. The corresponding 'end-ns' event does not have a value (None).
    #         It is common practice to use a list as namespace stack and pop the last entry on the 'end-ns' event
    #        
    #        Example of the events
    #          <root>
    #            <element key='value'>text</element>
    #            <element>text</element>tail
    #            <empty-element xmlns="http://testns/" />
    #          </root>
    #        
    #          >>> events = ("start", "end", "start-ns", "end-ns")
    #          >>> context = etree.iterparse(StringIO(xml), events=events)
    #          >>> for action, elem in context:
    #          ...     if action in ('start', 'end'):
    #          ...         print("%s: %s" % (action, elem.tag))
    #          ...     elif action == 'start-ns':
    #          ...         print("%s: %s" % (action, elem))
    #          ...     else:
    #          ...         print(action)
    #          start: root
    #          start: element
    #          end: element
    #          start: element
    #          end: element
    #          start-ns: ('', 'http://testns/')
    #          start: {http://testns/}empty-element
    #          end: {http://testns/}empty-element
    #          end-ns
    #          end: root
     
        # pre-parse wsdl and attach namespace information to each element
        root_element_tree = None
        ns_map = []       
        events = "start", "end", "start-ns", "end-ns"        
        for event, elem in ElementTree.iterparse(xml_fo, events):
            if event == "start-ns":
                # add the namespace mapping
                ns_map.append(elem)
            elif event == "end-ns":
                # pop up the last added namespace mapping
                ns_map.pop()
            elif event == "start":
                if root_element_tree is None:
                    root_element_tree = elem
                # add the list of namespace mappings to the element so it has access to it through ns_map variable
                elem.ns_map = dict(ns_map)
            elif event == "end":
                # do nothing
                pass
        return root_element_tree                
        
    def parse_xs_import_children(self, element):
        """
        Parses the child xs:import elements and extracts the relevant data to return to caller.
        
        :param element: Parent element to parse for xs:import child elements.
        :rtype: List of tuples. Each tuple(namespace, schema_location) representing the information from an import element.
        """             
        imports = []
        for import_element in element.findall('./{http://www.w3.org/2001/XMLSchema}import'):
            imp_namespace = import_element.attrib['namespace']
            imp_schema_location = import_element.attrib['schemaLocation']    
            imports.append((imp_namespace,imp_schema_location))
        return imports

    def find_message_element_by_name(self, message_prefixed_qualified_name, definitions_element):
        """
        Searches the wsdl definition element for a child message element matching "message_element_name".
        If found, it returns the message element, if not, it returns None.
        
        :param message_prefixed_qualified_name: Name of the message we are looking for. Name Expected to a be a Prefixed Qualified Name (e.g. nsprefix:ElementName)
        :rtype: List of tuples. Each tuple(namespace, schema_location) representing the information from an import element.
        """                    
        matches = prefixed_qualified_name_pattern.match(message_prefixed_qualified_name)
        # we ignore the prefix as we are assuming that the message is going to be defined in the target namespace. (i.e in the same wsdl file)
        message_element_name = matches.group(2)
        for message_element in definitions_element.findall('./{http://schemas.xmlsoap.org/wsdl/}message'):
            if message_element_name == message_element.attrib['name']:
                return message_element
        return None

    def create_type(self, prefix_qualified_name, current_element, uri_location, resource_artefacts):
        """
        Creates a resource of type="term:eplanning/edais/schema/type" based on information passed in. It then places
        the resource in the resource artefacts dictionary against its uri. This uri is returned. This function is called
        when we come across an attribute in a element where its value referes to a Type. We want to capture the 
        information in a resource of type="term:eplanning/edais/schema/type".
        
        :param prefix_qualified_name: String of the name of the type. Name Expected to a be a Prefixed Qualified Name (e.g. nsprefix:TypeName)
        :param current_element: Current element whose has a attribute that refers to a type.
        :param uri_location: Uri object that indicates where this resource will be stored in Spaces.
        :param resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the resource created will be located in spaces.
        """            
        matches = prefixed_qualified_name_pattern.match(prefix_qualified_name)
        type = Resource(type="term:eplanning/edais/schema/type")
        type.name = matches.group(2)
        type.namespace_prefix = matches.group(1)
        type.namespace = current_element.ns_map[type.namespace_prefix]
        type_uri = uri_location
        resource_artefacts[type_uri] = type
        return type_uri

    def parse_message(self, message_element, uri_location, wsdl_resource_artefacts):
        """
        Parses the wsdl:message element in a wsdl. It assumes there is only ONE PART to a message, and
        creates a resource of type="term:eplanning/edais/schema/type" to capture the type of the message. It returns the uri of the location
        of the type.
        
        :param message_element: Message element of which we want to parse for the type of the message.
        :param uri_location: Uri object that indicates where this resource will be stored in Spaces.
        :param wsdl_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the resource created will be located in spaces.
        """          
        # assume one part per message
        part_element = message_element.find('./{http://schemas.xmlsoap.org/wsdl/}part')
        type_uri = self.create_type(part_element.attrib['element'], part_element, uri_location, wsdl_resource_artefacts)
        return type_uri

    def parse_attribute(self, attribute_element, uri_prefix, schema_resource_artefacts):
        """
        Parses the xs:attribute element in a schema. It creates a resource of 
        type="term:eplanning/edais/schema/attribute" to capture the data of the attribute. 
        It returns the uri of the location of the attribute resource.
        
        :param attribute_element: Attribute element to parse.
        :param uri_prefix: Uri object that indicates the prefix of the Uri where this resource will be stored in Spaces.
        :param schema_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the attribute resource created will be located in spaces.
        """           
        attribute = Resource(type="term:eplanning/edais/schema/attribute")
        attribute.name = attribute_element.attrib['name']
        attribute_uri = uri_prefix + Uri("/".join(["attribute", attribute.name]))
        schema_resource_artefacts[attribute_uri] = attribute
        attribute_type_uri = self.create_type(attribute_element.attrib['type'], attribute_element, attribute_uri + Uri("type"), schema_resource_artefacts)
        attribute.type = attribute_type_uri
        if attribute_element.attrib['type'] != 'xs:string':
            print attribute_element.attrib['type']
        if 'use' in attribute_element.attrib: 
            if attribute_element.attrib['use'] == 'required':
                attribute.use = True
            else:
                attribute.use = False
        else:
            attribute.use = False
        if 'default' in attribute_element.attrib:
            attribute.default = attribute_element.attrib['default']
        else:
            attribute.default = None
        return attribute_uri
    
    def parse_simple_content_element(self, simple_content_element, uri_prefix, schema_resource_artefacts):
        """
        Parses the xs:simpleContent element in a schema. It creates a resource of 
        type="term:eplanning/edais/schema/simplecontent" to capture the data of the simpleContent. 
        It returns the uri of the location of the simple content resource.
        
        :param simple_content_element: SimpleContent element to parse.
        :param uri_prefix: Uri object that indicates the prefix of the Uri where this resource will be stored in Spaces.
        :param schema_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the simple content resource created will be located in spaces.
        """         
        simple_content = Resource(type="term:eplanning/edais/schema/simplecontent")
        simple_content_uri = uri_prefix + Uri("simplecontent")
        schema_resource_artefacts[simple_content_uri] = simple_content
        extension_element = simple_content_element.find('./{http://www.w3.org/2001/XMLSchema}extension')
        extension_type_uri = self.create_type(extension_element.attrib['base'], extension_element, simple_content_uri + Uri("extension"), schema_resource_artefacts)
        simple_content.extension = extension_type_uri
        simple_content.attributes = []
        for attribute_element in extension_element.findall('./{http://www.w3.org/2001/XMLSchema}attribute'):
            attribute_uri = self.parse_attribute(attribute_element, simple_content_uri, schema_resource_artefacts)
            simple_content.attributes.append(attribute_uri)
        return simple_content_uri

    def parse_element(self, element_element, uri_prefix, schema_resource_artefacts):
        """
        Parses the xs:element element in a schema. It creates a resource of 
        type="term:eplanning/edais/schema/element" to capture the data of the element. 
        It returns the uri of the location of the element resource.
        
        :param element_element: Element element to parse.
        :param uri_prefix: Uri object that indicates the prefix of the Uri where this resource will be stored in Spaces.
        :param schema_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the element resource created will be located in spaces.
        """        
        element = Resource(type="term:eplanning/edais/schema/element")
        element.name = element_element.attrib['name']
        element_uri = uri_prefix + Uri("element/%s" % element.name)
        schema_resource_artefacts[element_uri] = element        
        if 'minOccurs' in element_element.attrib:
            element.min_occurs = int(element_element.attrib['minOccurs'])
        else:
            element.min_occurs = 1
        if 'maxOccurs' in element_element.attrib:
            max_occurs = element_element.attrib['maxOccurs']
            if max_occurs != 'unbounded':
                element.max_occurs = int(element_element.attrib['maxOccurs'])
            else:
                element.max_occurs = -1
        else:
            element.max_occurs = 1        
        type_string = element_element.attrib['type']
        # type_string form is "nsPrefix:typeName"
        element_type_uri = self.create_type(type_string, element_element, element_uri + Uri("type"), schema_resource_artefacts)              
        element.type = element_type_uri
        return element_uri
        
    def parse_complex_type_element(self, complex_type_element, uri_prefix, schema_resource_artefacts):
        """
        Parses the xs:complexType element in a schema. It creates a resource of 
        type="term:eplanning/edais/schema/complextype" to capture the data of the complex type. 
        It returns the uri of the location of the complex type resource.
        
        :param complex_type_element: Complex Type element to parse.
        :param uri_prefix: Uri object that indicates the prefix of the Uri where this resource will be stored in Spaces.
        :param schema_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the complex type resource created will be located in spaces.
        """
        complex_type = Resource(type="term:eplanning/edais/schema/complextype")
        complex_type.name = complex_type_element.attrib['name']
        complex_type_uri = uri_prefix  + Uri("complextype/%s" % complex_type.name)
        schema_resource_artefacts[complex_type_uri] = complex_type
        complex_type.elements = []        
        simple_content_element = complex_type_element.find('./{http://www.w3.org/2001/XMLSchema}simpleContent')
        if simple_content_element:
            # most likely a complex type with simple content (e.g. no elements)
            complex_type.simple_content = self.parse_simple_content_element(simple_content_element, complex_type_uri, schema_resource_artefacts)
        else:
            sequence_element = complex_type_element.find('./{http://www.w3.org/2001/XMLSchema}sequence')
            # most likely a complex type with complex content (e.g. with elements)
            for element_or_choice_element in sequence_element.getchildren():
                if element_or_choice_element.tag == '{http://www.w3.org/2001/XMLSchema}choice':
                    choice_element = element_or_choice_element
                    for element_element in choice_element.findall('./{http://www.w3.org/2001/XMLSchema}element'):
                        element_uri = self.parse_element(element_element, complex_type_uri, schema_resource_artefacts)
                        complex_type.elements.append(element_uri)
                else:
                    element_uri = self.parse_element(element_or_choice_element, complex_type_uri, schema_resource_artefacts)
                    complex_type.elements.append(element_uri)
        complex_type.attributes = []                
        for attribute_element in complex_type_element.findall('./{http://www.w3.org/2001/XMLSchema}attribute'):
            attribute_uri = self.parse_attribute(attribute_element, complex_type_uri, schema_resource_artefacts)
            complex_type.attributes.append(attribute_uri)
        return complex_type_uri

    def parse_simple_type_element(self, simple_type_element, uri_prefix, schema_resource_artefacts):
        """
        Parses the xs:simpleType element in a schema. It creates a resource of 
        type="term:eplanning/edais/schema/simpletype" to capture the data of the simple type. 
        It returns the uri of the location of the simple type resource.
        
        :param simple_type_element: Simple Type element to parse.
        :param uri_prefix: Uri object that indicates the prefix of the Uri where this resource will be stored in Spaces.
        :param schema_resource_artefacts: Dictionary that contains resource artefacts(value) and their uri location in spaces(key). 
        :rtype: Uri of where the simple type resource created will be located in spaces.
        """        
        simple_type = Resource(type="term:eplanning/edais/schema/simpletype")
        simple_type.name = simple_type_element.attrib['name']
        simple_type_uri = uri_prefix + Uri("simpletype/%s" % simple_type.name)
        schema_resource_artefacts[simple_type_uri] = simple_type
        restriction_element = simple_type_element.find('./{http://www.w3.org/2001/XMLSchema}restriction')
        simple_type_restriction_type_uri = self.create_type(restriction_element.attrib['base'], restriction_element, simple_type_uri + Uri("restriction"), schema_resource_artefacts)
        simple_type.restriction = simple_type_restriction_type_uri
        simple_type.enums = {}
        for enumeration_element in restriction_element.findall('./{http://www.w3.org/2001/XMLSchema}enumeration'):
            value = enumeration_element.attrib['value']
            simple_type.enums[value] = value
        return simple_type_uri
    
    def generate_wsdl_resource_artefacts(self, wsdl_rs):
        """
        Takes a resource of type="term:eplanning/edais/wsdl" and creates wsdl resource artefacts.
        It returns the artefacts in a dictionary where the key is the uri of where the artefact
        should be stored in spaces.
        
        :param wsdl_rs: Resource of type="term:eplanning/edais/wsdl" 
        :rtype: Dictionary where key="Uri", value="Artefact Resouce"
        """ 
        wsdl_resource_artefacts = {}
        ws_name = wsdl_rs.get_metadata(Uri('dc:title'))
        wsdl_fo = StringIO.StringIO(wsdl_rs.file_content)
        wsdl_definitions_element = self.pre_parse_xml_to_add_namespace_data_to_elements(wsdl_fo)
        wsdl_definitions_uri = Uri("internal:eplanning/edais/wsdl/%s/definitions" % ws_name)        
        wsdl_definitions = Resource(type="term:eplanning/edais/wsdl/defintions")
        wsdl_resource_artefacts[wsdl_definitions_uri] = wsdl_definitions
        wsdl_definitions.target_namespace = wsdl_definitions_element.attrib['targetNamespace']
        wsdl_definitions.imported_namespaces = wsdl_definitions_element.ns_map
        
        types_element = wsdl_definitions_element.find('./{http://schemas.xmlsoap.org/wsdl/}types')
        schema_element = types_element.find('./{http://www.w3.org/2001/XMLSchema}schema')
        schema =  Resource(type="term:eplanning/edais/schema/schema")
        schema_uri = Uri("internal:eplanning/edais/wsdl/%s/definitions/schema" % ws_name)
        wsdl_resource_artefacts[schema_uri] = schema
        wsdl_definitions.schmea = schema_uri
        schema.target_namespace = schema_element.attrib['targetNamespace']
        schema.imported_namespaces = schema_element.ns_map
        
        # get imports
        schema.imports = self.parse_xs_import_children(schema_element)
            
        # get service
        service_element = wsdl_definitions_element.find('./{http://schemas.xmlsoap.org/wsdl/}service')
        # get port
        # assume one port per service
        port_element = service_element.find('./{http://schemas.xmlsoap.org/wsdl/}port')
        address_element = port_element.find('./{http://schemas.xmlsoap.org/wsdl/soap/}address')
        wsdl_definitions.service_endpoint = address_element.attrib['location']

        # assume one binding in the same wsdl and assume http binding
        wsdl_definitions.operations = {}
        binding_element = wsdl_definitions_element.find('./{http://schemas.xmlsoap.org/wsdl/}binding')
        for operation_element in binding_element.findall('./{http://schemas.xmlsoap.org/wsdl/}operation'):
            operation = Resource(type="term:eplanning/edais/wsdl/operation")
            operation.name = operation_element.attrib['name']
            operation_uri = Uri("internal:eplanning/edais/wsdl/%s/definitions/operation/%s" % (ws_name, operation.name))
            wsdl_resource_artefacts[operation_uri] = operation
            operation.soap_action = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/soap/}operation').attrib['soapAction'] 
            wsdl_definitions.operations[operation.name] = operation_uri
            
        # get port type
        port_type_element = wsdl_definitions_element.find('./{http://schemas.xmlsoap.org/wsdl/}portType')            

        # get operation
        operation_message_prefix_uri = Uri("internal:eplanning/edais/wsdl/%s/definitions/operation/%s" % (ws_name, operation.name))
        for operation_element in port_type_element.findall('./{http://schemas.xmlsoap.org/wsdl/}operation'):
            operation = wsdl_resource_artefacts[Uri("internal:eplanning/edais/wsdl/%s/definitions/operation/%s" % (ws_name, operation_element.attrib['name']))]
            input_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}input')
            input_message_element = self.find_message_element_by_name(input_element.attrib['message'], wsdl_definitions_element)
            input_type_uri = self.parse_message(input_message_element, operation_message_prefix_uri + Uri("input"), wsdl_resource_artefacts)
            operation.input = input_type_uri
            
            output_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}output')
            if output_element:
                output_message_element = self.find_message_element_by_name(output_element.attrib['message'], wsdl_definitions_element)
                output_type_uri = self.parse_message(output_message_element, operation_message_prefix_uri + Uri("output"), wsdl_resource_artefacts)
                operation.output = output_type_uri
            
            fault_element = operation_element.find('./{http://schemas.xmlsoap.org/wsdl/}fault')
            if fault_element:
                fault_message_element = self.find_message_element_by_name(fault_element.attrib['message'], wsdl_definitions_element)
                fault_type_uri = self.parse_message(fault_message_element, operation_message_prefix_uri + Uri("fault"), wsdl_resource_artefacts)
                operation.fault = fault_type_uri
        
        return wsdl_resource_artefacts
    
    def generate_schema_resource_artefacts(self, schema_rs):
        """
        Takes a resource of type="term:eplanning/edais/schema" and creates schema resource artefacts.
        It returns the artefacts in a dictionary where the key is the uri of where the artefact
        should be stored in spaces.
        
        :param schema_rs: Resource of type="term:eplanning/edais/schema" 
        :rtype: Dictionary where key="Uri", value="Artefact Resouce"
        """ 
        schema_resource_artefacts = {}
        schema_name = schema_rs.get_metadata(Uri('dc:title'))
#        print schema_name
        schema_fo = StringIO.StringIO(schema_rs.file_content)
        schema_element = self.pre_parse_xml_to_add_namespace_data_to_elements(schema_fo)
        schema_uri = Uri("internal:eplanning/edais/schema/%s" % schema_name)  
        schema = Resource(type="term:eplanning/edais/schema/schema")
        schema.target_namespace = schema_element.attrib['targetNamespace']
        schema.imported_namespaces = schema_element.ns_map
    
        # get imports
        schema.imports = self.parse_xs_import_children(schema_element)

        # parse complex types
        schema.complex_types = []
        for complex_type_element in schema_element.findall('./{http://www.w3.org/2001/XMLSchema}complexType'):
            complex_type_uri = self.parse_complex_type_element(complex_type_element, schema_uri, schema_resource_artefacts)
            schema.complex_types.append(complex_type_uri)        

        # parse simple types
        schema.simple_types = []
        for simple_type_element in schema_element.findall('./{http://www.w3.org/2001/XMLSchema}simpleType'):
            simple_type_uri = self.parse_simple_type_element(simple_type_element, schema_uri, schema_resource_artefacts)
            schema.simple_types.append(simple_type_uri)
        
        # parse elements
        schema.elements = []
        for element_element in schema_element.findall('./{http://www.w3.org/2001/XMLSchema}element'):
            element_uri = self.parse_element(element_element, schema_uri, schema_resource_artefacts)
            schema.elements.append(element_uri)
        
        return schema_resource_artefacts
              
    def generate_wsdls_and_schemas_resources(self, wsdls, schemas):
        """
        Takes a resources of type="term:eplanning/edais/wsdl" and
        type="term:eplanning/edais/schema" and creates wsdl and schema resource artefacts.
        It returns the artefacts in dictionares where the key is the uri of where the artefact
        should be stored in spaces.
        
        :param wsdls: list of resources of type="term:eplanning/edais/wsdl"
        :param schemas: list of resources of type="term:eplanning/edais/schema" 
        :rtype: Tuple containing two dictionaries (all_wsdl_resource_artefacts_dictonary, all_schema_resource_artefacts_dictionary). 
        """ 
        all_wsdl_resource_artefacts = {}
        all_schema_resource_artefacts = {}
        num_wsdl_resource_artefacts = 0
        num_schema_resource_artefacts = 0
        for wsdl in wsdls:
            wsdl_resource_artefacts = self.generate_wsdl_resource_artefacts(wsdl)
            num_wsdl_resource_artefacts += len(wsdl_resource_artefacts)
            all_wsdl_resource_artefacts.update(wsdl_resource_artefacts)                
        for schema in schemas:
            schema_resource_artefacts = self.generate_schema_resource_artefacts(schema)
            num_schema_resource_artefacts += len(schema_resource_artefacts)
            all_schema_resource_artefacts.update(schema_resource_artefacts)
        if num_wsdl_resource_artefacts != len(all_wsdl_resource_artefacts) or num_schema_resource_artefacts != len(all_schema_resource_artefacts):
            raise Exception()
        return (all_wsdl_resource_artefacts, all_schema_resource_artefacts)